Este documento describe el proceso técnico para integrar el sistema de gestión OTEC con la API del Sistema Integrado de Capacitación (SIC) de SENCE. El objetivo principal es permitir el envío periódico y automatizado de la información de avance de los alumnos en los cursos, de acuerdo con los requerimientos establecidos por SENCE.
La integración se basa en un modelo de "tablas de staging" o "tablas de preparación" para consolidar y formatear los datos antes de su transmisión a la API REST del Gestor Intermedio de SENCE. Esta guía está destinada a programadores y personal técnico encargado de implementar y mantener dicha integración.
Convenciones de Nomenclatura:
La estrategia central de esta integración es la creación de un conjunto de tablas en la base de datos local, denominadas "tablas de staging". Estas tablas servirán como un área intermedia donde los datos requeridos por SENCE se recopilarán, transformarán y almacenarán con el formato adecuado antes de ser enviados a la API.
Este enfoque ofrece las siguientes ventajas:
El flujo general será:
Se crearán las siguientes tablas con el prefijo
Esta tabla registrará cada intento de envío a SENCE, permitiendo su seguimiento y auditoría.
CREATE TABLE IF NOT EXISTS sence_envios_programados (
id INT AUTO_INCREMENT PRIMARY KEY,
fecha_programada_envio DATE NOT NULL COMMENT 'Fecha para la cual se preparan los datos del reporte',
codigo_envio_otec VARCHAR(255) NULL COMMENT 'ID interno opcional del OTEC para este envío (codigoEnvio SENCE)',
rut_otec VARCHAR(12) NOT NULL COMMENT 'RUT del OTEC, ej: 76000111-K',
id_sistema_sence INT NOT NULL DEFAULT 1350 COMMENT 'ID Fijo SENCE para LMS externas',
token_sence_usado VARCHAR(255) NOT NULL COMMENT 'Token de autenticación SENCE utilizado',
estado_actual_envio ENUM('pendiente', 'procesando_json', 'enviado_a_sence', 'exitoso_sence', 'error_otec', 'error_sence') NOT NULL DEFAULT 'pendiente',
fecha_creacion_registro TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
fecha_ultimo_intento_envio DATETIME NULL,
sence_id_proceso_respuesta VARCHAR(255) NULL COMMENT 'ID del proceso devuelto por SENCE tras un envío exitoso',
sence_log_respuesta TEXT NULL COMMENT 'Respuesta JSON completa de la API SENCE',
INDEX idx_fecha_programada_envio (fecha_programada_envio),
INDEX idx_estado_envio (estado_actual_envio)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Contendrá la información a nivel de curso para un lote de envío específico.
CREATE TABLE IF NOT EXISTS sence_staging_cursos (
id INT AUTO_INCREMENT PRIMARY KEY,
envio_programado_id INT NOT NULL COMMENT 'FK a sence_envios_programados.id',
id_curso_otec INT NOT NULL COMMENT 'FK al ID del curso en la tabla local cursos_sence',
codigoOferta VARCHAR(255) NOT NULL COMMENT 'Código del curso SENCE (ej. registro_nacional)',
codigoGrupo VARCHAR(255) NOT NULL COMMENT 'Código de la sección/grupo SENCE (a menudo igual a codigoOferta)',
cantActividadSincronica_curso INT DEFAULT 0 COMMENT 'Número total de actividades sincrónicas del curso',
cantActividadAsincronica_curso INT DEFAULT 0 COMMENT 'Número total de actividades asincrónicas del curso',
fecha_actualizacion_staging TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (envio_programado_id) REFERENCES sence_envios_programados(id) ON DELETE CASCADE,
FOREIGN KEY (id_curso_otec) REFERENCES cursos_sence(id) ON DELETE RESTRICT,
UNIQUE KEY uq_envio_curso (envio_programado_id, id_curso_otec)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Datos de cada alumno dentro de un curso, para un lote de envío.
CREATE TABLE IF NOT EXISTS sence_staging_alumnos (
id INT AUTO_INCREMENT PRIMARY KEY,
staging_curso_id INT NOT NULL COMMENT 'FK a sence_staging_cursos.id',
id_alumno_otec INT NOT NULL COMMENT 'FK al ID del alumno en la tabla local alumnos',
id_inscripcion_otec INT NOT NULL COMMENT 'FK al ID de la inscripción en la tabla local inscripciones_curso',
rutAlumno VARCHAR(10) NOT NULL COMMENT 'RUT del alumno sin dígito verificador (parte numérica)',
dvAlumno VARCHAR(1) NOT NULL COMMENT 'Dígito verificador del alumno',
tiempoConectividad_total_curso INT DEFAULT 0 COMMENT 'Tiempo total de conectividad del alumno en el curso (segundos)',
estado_sence_curso INT NOT NULL COMMENT 'Estado SENCE: 1=Cursando, 2=Aprobado, 3=Reprobado',
porcentajeAvance_total_curso INT DEFAULT 0 COMMENT 'Porcentaje de avance general del alumno en el curso (0-100)',
fechaInicio_curso_alumno DATE NOT NULL COMMENT 'Fecha de inicio del curso para el alumno (YYYY-MM-DD)',
fechaFin_curso_alumno DATE NOT NULL COMMENT 'Fecha de término del curso para el alumno (YYYY-MM-DD)',
fechaEjecucion_reporte DATE NOT NULL COMMENT 'Fecha a la que corresponde el avance reportado (YYYY-MM-DD)',
evaluacionFinal_curso INT DEFAULT NULL COMMENT 'Nota final del alumno en el curso (0-100)',
fecha_actualizacion_staging TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (staging_curso_id) REFERENCES sence_staging_cursos(id) ON DELETE CASCADE,
FOREIGN KEY (id_alumno_otec) REFERENCES alumnos(id) ON DELETE RESTRICT,
FOREIGN KEY (id_inscripcion_otec) REFERENCES inscripciones_curso(id) ON DELETE RESTRICT,
UNIQUE KEY uq_stag_curso_alumno (staging_curso_id, id_alumno_otec)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Datos de cada módulo (interno: "tema") cursado por un alumno, para un lote de envío.
CREATE TABLE IF NOT EXISTS sence_staging_modulos_alumno (
id INT AUTO_INCREMENT PRIMARY KEY,
staging_alumno_id INT NOT NULL COMMENT 'FK a sence_staging_alumnos.id',
id_tema_otec INT NOT NULL COMMENT 'FK al ID del tema en la tabla local temas_curso',
codigoModulo VARCHAR(255) NOT NULL COMMENT 'Código SENCE del módulo (proveniente de temas_curso)',
tiempoConectividad_modulo INT DEFAULT 0 COMMENT 'Tiempo de conectividad del alumno en este módulo (segundos)',
estado_sence_modulo INT NOT NULL COMMENT 'Estado SENCE del alumno en el módulo: 1=Cursando, 2=Aprobado, 3=Reprobado',
porcentajeAvance_modulo INT DEFAULT 0 COMMENT 'Porcentaje de avance del alumno en este módulo (0-100)',
fechaInicio_modulo_alumno DATE NULL COMMENT 'Fecha de inicio del módulo para el alumno (YYYY-MM-DD)',
fechaFin_modulo_alumno DATE NULL COMMENT 'Fecha de término del módulo para el alumno (YYYY-MM-DD)',
notaModulo INT DEFAULT NULL COMMENT 'Nota del alumno en el módulo (0-100)',
cantActividadSincronica_modulo_def INT DEFAULT 0 COMMENT 'N° act. sincrónicas (definición del módulo)',
cantActividadAsincronica_modulo_def INT DEFAULT 0 COMMENT 'N° act. asincrónicas (definición del módulo)',
fecha_actualizacion_staging TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (staging_alumno_id) REFERENCES sence_staging_alumnos(id) ON DELETE CASCADE,
FOREIGN KEY (id_tema_otec) REFERENCES temas_curso(id) ON DELETE RESTRICT,
UNIQUE KEY uq_stag_alumno_modulo (staging_alumno_id, id_tema_otec)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Datos de cada actividad (interno: "subtema") dentro de un módulo, para un lote de envío. SENCE no pide muchos detalles aquí en el JSON, pero registrar su "código" es fundamental.
CREATE TABLE IF NOT EXISTS sence_staging_actividades_alumno (
id INT AUTO_INCREMENT PRIMARY KEY,
staging_modulo_alumno_id INT NOT NULL COMMENT 'FK a sence_staging_modulos_alumno.id',
id_subtema_otec INT NOT NULL COMMENT 'FK al ID del subtema en la tabla local subtemas_curso',
codigoActividad VARCHAR(50) NOT NULL COMMENT 'Nombre o ID de la actividad SENCE (max 50 chars)',
-- Se podría agregar un campo 'completada' (BOOLEAN) si ayuda a calcular el % de avance del módulo.
fecha_actualizacion_staging TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (staging_modulo_alumno_id) REFERENCES sence_staging_modulos_alumno(id) ON DELETE CASCADE,
FOREIGN KEY (id_subtema_otec) REFERENCES subtemas_curso(id) ON DELETE RESTRICT,
UNIQUE KEY uq_stag_modulo_actividad (staging_modulo_alumno_id, id_subtema_otec)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Para asegurar la correcta correspondencia de datos, se establece el siguiente mapeo conceptual:
Las tablas de staging se poblarán mediante una combinación de actualizaciones incrementales desde los scripts existentes y un proceso de consolidación por lotes.
Estos scripts tendrán un rol menor, principalmente para datos identificatorios y estados iniciales:
Esta es la parte más dinámica. Los scripts que manejan la interacción del alumno con el contenido del curso deben actualizar las tablas de staging:
Nota Importante: Las actualizaciones frecuentes por progreso podrían generar mucha carga. Una alternativa es que estos scripts actualicen las tablas de producción (
Este script es fundamental y se recomienda ejecutarlo mediante una tarea programada (CRON) diariamente, antes de la ventana de envío sugerida por SENCE (22:00-00:00 hrs).
Funciones Principales:
Una vez que los datos están preparados en las tablas de staging, otro script se encargará de construir el JSON y enviarlo a SENCE.
Este script puede ser llamado manualmente o también programado para ejecutarse después del script de consolidación.
Funciones Principales:
// Ejemplo conceptual en PHP con cURL para timeout
// curl_setopt($ch, CURLOPT_TIMEOUT, 600); // 10 minutos
// ini_set('max_execution_time', 600); // PHP script execution time
El JSON debe seguir la estructura detallada en el "Instructivo de Conexión: Integración entre LMS y SIC".
{
"rutOtec": "76000111-K", // Ejemplo
"idSistema": 1350,
"token": "TOKEN-SENCE-OBTENIDO", // UUID en MAYÚSCULAS
"codigoOferta": "CODIGO-CURSO-SENCE",
"codigoGrupo": "CODIGO-SECCION-SENCE", // A menudo el mismo que codigoOferta
"codigoEnvio": "ID-INTERNO-LOTE-OTEC-OPCIONAL",
"cantActividadSincronica": 0, // Total actividades sincrónicas del CURSO
"cantActividadAsincronica": 0, // Total actividades asincrónicas del CURSO
"listaAlumnos": [
{
"rutAlumno": "11111111", // Sin DV
"dvAlumno": "1",
"tiempoConectividad": 3600, // Segundos, total del alumno en el CURSO
"estado": 1, // 1:Cursando, 2:Aprobado, 3:Reprobado (en el CURSO)
"porcentajeAvance": 50, // 0-100, avance general del alumno en el CURSO
"fechaInicio": "2023-01-15", // Inicio del alumno en el CURSO
"fechaFin": "2023-06-15", // Fin del alumno en el CURSO
"fechaEjecucion": "2023-05-25", // Fecha del reporte
"evaluacionFinal": 75, // 0-100, nota final del alumno en el CURSO
"listaModulos": [
{
"codigoModulo": "CODIGO-SENCE-MODULO-1",
"tiempoConectividad": 1800, // Segundos, del alumno en este MÓDULO
"estado": 1, // 1:Cursando, 2:Aprobado, 3:Reprobado (en este MÓDULO)
"porcentajeAvance": 70, // 0-100, avance del alumno en este MÓDULO
"fechaInicio": "2023-01-15", // Inicio del MÓDULO (puede ser igual al del curso)
"fechaFin": "2023-03-15", // Fin del MÓDULO
"notaModulo": 80, // 0-100, nota del alumno en este MÓDULO
"cantActividadSincronica": 0, // Total act. sincrónicas (definición del MÓDULO)
"cantActividadAsincronica": 0, // Total act. asincrónicas (definición del MÓDULO)
"listaActividades": [
{ "codigoActividad": "Nombre o ID Actividad 1.1" }, // Máx 50 chars, se trunca
{ "codigoActividad": "Nombre o ID Actividad 1.2" }
]
}
// ... más módulos para este alumno
]
}
// ... más alumnos para este curso
]
}
Los campos y sus tipos de datos se encuentran en el instructivo de SENCE.
Si la información se envía correctamente, la API responderá con un JSON que incluye un id_proceso. Este ID es importante para seguimiento.
En caso de errores en los datos o en la estructura, la API devolverá un JSON con un campo datosError y/o un código de error específico.
Códigos de Error Comunes de SENCE (Resumen):
Código Error | Texto Error | Descripción Breve |
---|---|---|
001 | Token inválido | Datos de autenticación (idSistema, RUT, token) no válidos. |
003 | El curso (codigoCurso) no se encuentra registrado | Código de curso enviado no existe en Gestor Intermedio. |
011 | El alumno (rutAlumno) no se encuentra registrado en este curso. | Alumno registrado en SENCE pero no en el curso especificado. |
012 | El alumno (rutAlumno) no se encuentra registrado. | Alumno no existe en la plataforma SENCE. |
021 | alumno.tiempoConectividad inválido | Tiempo no numérico o menor a 0. |
022 | alumno.porcentajeAvance inválido | Porcentaje no numérico o fuera de rango. |
025 | modulo.porcentajeAvance debe ser mayor al anterior (porcentajeAnterior) | Se envió un % de avance menor al ya ingresado. |
SENCE proporciona un entorno y datos de prueba para validar la integración antes de enviar información de cursos reales.
La implementación de un sistema de tablas de staging y scripts dedicados para la consolidación y envío de datos a la API de SENCE proporciona una solución robusta y mantenible. Siguiendo los pasos y consideraciones detalladas en este documento, cualquier programador con acceso a la base de datos y al código PHP del sistema OTEC debería ser capaz de implementar, probar y mantener esta integración.
Es crucial prestar atención a los detalles de formato de datos, mapeo de estados y códigos, y el manejo correcto de la autenticación y respuestas de la API SENCE. La documentación oficial de SENCE debe ser consultada como referencia principal durante todo el proceso.